package com.yishun.springboot.service;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.http.HttpUtil;
import com.RequestGongWuShu.Crane;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.protobuf.TextFormat.ParseException;
import com.yishun.springboot.httpclient.Post8806;
import com.yishun.springboot.mapper.GongWuSuTimedUpLoadCraneMapper;
import com.yishun.springboot.mapper.GwsCraneElectrifyDTOMapper;
import com.yishun.springboot.pojo.GwsCraneElectrifyDTO;
import com.yishun.springboot.util.GwsRedisUtil;
import com.yishun.springboot.util.SignatureUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.*;

@Slf4j
@Service
@Component
public class GongWuSuTimedUpLoadCraneService {

    @Autowired
    GongWuSuTimedUpLoadCraneMapper gongWuSuTimedUpLoadCraneMapper;

    @Autowired
    GwsCraneElectrifyDTOMapper gwsCraneElectrifyDTOMapper;

    @Autowired
    GwsRedisUtil redisUtil;

    /**
     * 2.3.7上报塔机实时数据
     */
    String url = "http://szwb.sz.gov.cn:2018/openapi";

    @Async(value = "asyncExecutor")
    @Scheduled(fixedRate = 1000 * 20)
    public void addRecord() {
        // 先查询出所有是否推送为是的设备数据 然后根据供应商设备编号查询实时数据 半小时内没数据为下班 半小时又有数据了为上班
        List<Map<String, Object>> listMap = gongWuSuTimedUpLoadCraneMapper.getProjectAll();
        for (Map<String, Object> li : listMap) {
            Map<String, Object> map = li;
            Integer id = (Integer) map.get("gws_crane_project_id");
            String apiKey = (String) map.get("api_key");
            String engCode = (String) map.get("engCode");
            String projectCode = (String) map.get("projectCode");
            String api_version = "1.0";

            // 1 表示查询出推送实时数据和预计数据的塔吊基础信息
            List<Map<String, Object>> deviceList = gongWuSuTimedUpLoadCraneMapper.findByProjectId(id, "1");

            for (Map<String, Object> res : deviceList) {
                Map<String, Object> bods = res;
                String deviceNo = (String) bods.get("device_no");// uuid32位 工务署设备编号
                String deviceCode = (String) bods.get("device_code");// 供应商设备编号
                Map<String, Object> craneMap = gongWuSuTimedUpLoadCraneMapper.getDeviceData(deviceCode);
                if(StringUtils.isEmpty(craneMap)){
                    continue;
                }
                JSONObject mapVal = new JSONObject();
                JSONObject mapValType = new JSONObject();
                mapVal.put("device_no", deviceNo);
                mapVal.put("runtime", DateUtil.now());
                mapVal.put("load", (double) craneMap.get("load"));
                mapVal.put("load_ratio", (double) craneMap.get("load_ratio") / 100);
                Float moment = new Float((Float) craneMap.get("moment"));
                mapVal.put("moment", moment.doubleValue());
                mapVal.put("moment_ratio", (double) craneMap.get("moment_ratio") / 100);
                mapVal.put("slewing_speed", (double) craneMap.get("slewing_speed"));
                double height = (double) craneMap.get("height");
                mapVal.put("height", height < 2 || height > 120 ? RandomUtil.randomDouble(2.0, 120.0) : height);
                mapVal.put("range", (double) craneMap.get("range"));
                mapVal.put("wind_speed", (double) craneMap.get("wind_speed"));
                Double wind_speed = (double) craneMap.get("wind_speed");
                if (wind_speed > 13.8) {
                    mapVal.put("wind_warn", 1);
                } else {
                    mapVal.put("wind_warn", 0);
                }

                Integer WarningType = (Integer) craneMap.get("WarningType");
                mapVal.put("is_up_warning", 0);
                if (WarningType == 103) {
                    mapVal.put("rotation_warn", 1);
                } else {
                    mapVal.put("rotation_warn", 0);
                }
                if (WarningType == 111 || WarningType == 112 || WarningType == 113 || WarningType == 114
                        || WarningType == 211 || WarningType == 212 || WarningType == 213 || WarningType == 214) {
                    mapVal.put("collision_warn", 1);
                } else {
                    mapVal.put("collision_warn", 0);
                }
                mapVal.put("is_left_warning", 0);
                mapVal.put("is_right_warning", 0);
                mapVal.put("is_forward_warning", 0);
                mapVal.put("is_backward_warning", 0);
                List<Object> listType = new ArrayList<Object>();
                List<Object> list = new ArrayList<Object>();
                list.add(mapVal);

                // 以上为实时数据 下为预警

                if (WarningType != 0) {
                    mapValType.put("device_no", deviceNo);
                    mapValType.put("runtime", DateUtil.now());
                    mapValType.put("load", (double) craneMap.get("load"));
                    mapValType.put("load_ratio", (double) craneMap.get("load_ratio"));
                    mapValType.put("moment", moment);
                    mapValType.put("moment_ratio", (double) craneMap.get("moment_ratio"));
                    mapValType.put("slewing_speed", (double) craneMap.get("slewing_speed"));
                    mapValType.put("height", (double) craneMap.get("height"));
                    mapValType.put("range", (double) craneMap.get("range"));
                    mapValType.put("wind_speed", (double) craneMap.get("wind_speed"));
                    listType.add(mapValType);
                    String bodyType = listType.toString();
                    String signatureType = SignatureUtil.getSignature(apiKey, api_version, engCode, projectCode, DateUtil.now(),
                            bodyType);
                    Map<String, Object> paramType = new HashMap<>();
                    paramType.put("api_key", apiKey);
                    paramType.put("project_code", projectCode);
                    paramType.put("eng_code", engCode);
                    paramType.put("api_version", api_version);
                    paramType.put("timestamp", DateUtil.now());
                    paramType.put("body", listType);
                    paramType.put("signature", signatureType);
                    JSONObject json2Type = new JSONObject(paramType);
                    String aType = json2Type.toJSONString();
                    log.info("All:" + aType);
                    if (listType.size() > 0) {
                        String infoType = HttpUtil.post(url + "/crane/warning", aType);
                        log.info("down!" + infoType);
                    }
                }
                // ******************************************************************************************************************************
                String body = list.toString();

                String signature = SignatureUtil.getSignature(apiKey, api_version, engCode, projectCode, DateUtil.now(),
                        body);
                Map<String, Object> param = new HashMap<>();
                param.put("api_key", apiKey);
                param.put("project_code", projectCode);
                param.put("eng_code", engCode);
                param.put("api_version", api_version);
                param.put("timestamp", DateUtil.now());
                param.put("body", list);
                param.put("signature", signature);
                JSONObject json2 = new JSONObject(param);
                String a = json2.toJSONString();
                log.info("All:" + a);
                String info = HttpUtil.post(url + "/crane/addRecord", a);
                log.info("down!" + info);


            }
        }
    }

    /**
     * 推送塔吊工作循环
     */
    @Async(value = "asyncExecutor")
    @Scheduled(fixedRate = 1000 * 60 * 60)
    public void pushCraneDutyCycle() {

        List<Map<String, Object>> listMap = gongWuSuTimedUpLoadCraneMapper.getProjectAll();

        // 项目编号
        Integer id = null;

        String apiKey = "";// 工务署key

        String engCode = "";// 工程编号

        String projectCode = "";// 项目编号

        JSONObject json = null;// 存储项目信息

        JSONObject deviceJsonObject = null;

        for (Map<String, Object> map : listMap) {
            json = new JSONObject(map);

            id = json.getInteger("gws_crane_project_id");

            List<Map<String, Object>> deviceList = gongWuSuTimedUpLoadCraneMapper.findByProjectId(id, "2");

            apiKey = json.getString("api_key");
            engCode = json.getString("engCode");
            projectCode = json.getString("projectCode");

            Crane.setApi_key(apiKey);
            Crane.setApi_version("1.0");
            Crane.setEngCode(engCode);
            Crane.setProjectCode(projectCode);

            for (Map<String, Object> deviceMap : deviceList) {
                deviceJsonObject = new JSONObject(deviceMap);

                String deviceCode = deviceJsonObject.getString("device_code");
                String deviceNo = deviceJsonObject.getString("device_no");

                JSONObject res = Post8806.getCraneDutyCycle(deviceCode);

                if (res == null) {
                    log.info(deviceCode + "获取0086工作循环失败");
                    continue;
                }

                JSONObject param = new JSONObject();

                param.put("device_no", deviceNo);
                param.put("start_time", res.getString("BeginTime"));
                param.put("end_time", res.getString("EndTime"));

                Double maxMoment = res.getDouble("MaxWeight");
                Double maxMomentPercent = maxMoment / 1000.0;
                // 格式化Double设置为保留一位小数，并且会进行四舍五入
                DecimalFormat df = new DecimalFormat("#.#");
                param.put("max_moment_ratio", df.format(maxMomentPercent));

                JSONObject resGws = Crane.workLoop(param);

                if (("false".equals(resGws.getString("result")))) {
                    log.info("工务署设备编号：" + deviceNo + "，推送塔吊工作循环失败，原因" + resGws.getString("detail_message"));
                }
            }
        }
    }

    @Async(value = "asyncExecutor")
    @Scheduled(fixedRate = 1000 * 60)
    public void pushCraneElectrify() {
        List<Map<String, Object>> listMap = gongWuSuTimedUpLoadCraneMapper.getProjectAll();

        // 项目编号
        Integer id = null;

        String apiKey = "";// 工务署key

        String engCode = "";// 工程编号

        String projectCode = "";// 项目编号

        JSONObject json = null;// 存储项目信息

        GwsCraneElectrifyDTO electrifyDTO = new GwsCraneElectrifyDTO();

        for (Map<String, Object> map : listMap) {
            json = new JSONObject(map);

            id = json.getInteger("gws_crane_project_id");

            List<GwsCraneElectrifyDTO> electrifyDTOs = gwsCraneElectrifyDTOMapper.getCraneElectrify(id, "3");

            for (int i = 0; i < electrifyDTOs.size(); i++) {
                electrifyDTO = electrifyDTOs.get(i);

                String deviceNo = electrifyDTO.getDevice_no();

                Integer operation = electrifyDTO.getOperation();

                Object redisRes = redisUtil.getCraneElectrify(deviceNo);

                // 已存储过redis就进行状态比对，如果状态相同该设备本次即可跳过
                if (redisRes != null) {
                    Integer operationRds = (Integer) redisRes;
                    if (operationRds == operation) {
                        continue;
                    }
                }

                apiKey = json.getString("api_key");
                engCode = json.getString("engCode");
                projectCode = json.getString("projectCode");

                Crane.setApi_key(apiKey);
                Crane.setApi_version("1.0");
                Crane.setEngCode(engCode);
                Crane.setProjectCode(projectCode);

                JSONObject jsonParam = JSONObject.parseObject(JSON.toJSONString(electrifyDTO));

                JSONObject httpRes = Crane.electrify(jsonParam);

                if (("false").equals(httpRes.getString("result"))) {
                    log.info("设备号：" + deviceNo + ",推送塔吊" + (operation == 1 ? "通电" : "断电") + "失败！");
                    continue;
                }

                // 推送成功存入一下redis，防止下次推送重复状态
                redisUtil.setCraneElectrify(deviceNo, operation);
            }
        }
    }

    @Async(value = "asyncExecutor")
    @Scheduled(cron = "* 30 6 * * ? ")
    public void clockIn() throws ParseException, java.text.ParseException {
        List<Map<String, Object>> listMap = gongWuSuTimedUpLoadCraneMapper.getProjectAll();
        String timestamp = DateUtil.format(new Date(), "yyyy-MM-dd HH:mm:ss");
        for (Map<String, Object> li : listMap) {
            Map<String, Object> map = li;
            Integer id = (Integer) map.get("gws_crane_project_id");
            String apiKey = (String) map.get("api_key");
            String engCode = (String) map.get("engCode");
            String projectCode = (String) map.get("projectCode");
            String api_version = "1.0";

            List<Map<String, Object>> deviceList = gongWuSuTimedUpLoadCraneMapper.findByProjectId(id, "4");

            for (Map<String, Object> res : deviceList) {
                Map<String, Object> bods = res;
                String deviceNo = (String) bods.get("device_no");// uuid32位 工务署设备编号
                String deviceCode = (String) bods.get("device_code");// 供应商设备编号
                String userName = gongWuSuTimedUpLoadCraneMapper.getCraneUser(deviceCode);

                SimpleDateFormat dateFormat1 = new SimpleDateFormat("yyyy-MM-dd ");
                String date1 = dateFormat1.format(DateUtil.parseCST(new Date().toString())) + "06:00:00";// 早上上班时间

                Calendar cal = Calendar.getInstance();
                cal.add(Calendar.MINUTE, -30);
                SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

                Integer cl1 = RandomUtil.randomInt(-10, 10);
                Integer cl1m = RandomUtil.randomInt(0, 59);
                try {
                    cal.setTime(dateFormat.parse(date1));// 这个为6点整早上上班时间
                } catch (java.text.ParseException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }

                cal.add(Calendar.SECOND, cl1m);
                cal.add(Calendar.MINUTE, cl1);

                String start_time = dateFormat.format(cal.getTime());// 上班时间

                String date = dateFormat1.format(DateUtil.parseCST(new Date().toString())) + "18:00:00";// 下午下班时间
                Integer cl = RandomUtil.randomInt(-2, 10);
                Integer clm = RandomUtil.randomInt(0, 59);
                cal.setTime(dateFormat.parse(date));// 这个为18点下午下班时间
                cal.add(Calendar.MINUTE, cl);
                cal.add(Calendar.SECOND, clm);

                String end_time = dateFormat.format(cal.getTime());// 下班时间

                List<Object> list = new ArrayList<Object>();
                JSONObject mapVal = new JSONObject();
                mapVal.put("start_time", start_time);
                mapVal.put("end_time", end_time);
                mapVal.put("worker_name", userName);
                mapVal.put("device_no", deviceNo);
                list.add(mapVal);

                String body = list.toString();

                String signature = SignatureUtil.getSignature(apiKey, api_version, engCode, projectCode, timestamp,
                        body);
                Map<String, Object> param = new HashMap<>();
                param.put("api_key", apiKey);
                param.put("project_code", projectCode);
                param.put("eng_code", engCode);
                param.put("api_version", api_version);
                param.put("timestamp", timestamp);
                param.put("body", list);
                param.put("signature", signature);
                JSONObject json2 = new JSONObject(param);
                String a = json2.toJSONString();
                log.info("All:" + a);
                String info = HttpUtil.post(url + "/crane/clockIn", a);
                log.info("down!" + info);
            }
        }
    }

}
